package com.jrx.anytxn.param.service.limit.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Maps;
import com.jrx.anytxn.i18n.response.TxnPage;
import com.jrx.anytxn.common.data.TxnRespCode;
import com.jrx.anytxn.common.exception.TxnBizException;
import com.jrx.anytxn.common.exception.TxnException;
import com.jrx.anytxn.common.uitl.BeanMapping;
import com.jrx.anytxn.common.uitl.StringUtils;
import com.jrx.anytxn.number.exception.SegmentException;
import com.jrx.anytxn.number.service.ISegmentService;
import com.jrx.anytxn.param.constant.Constant;
import com.jrx.anytxn.param.constant.ErrorMsgConstant;
import com.jrx.anytxn.param.dto.limit.CreditLimitTemplateReq;
import com.jrx.anytxn.param.dto.limit.CreditLimitTemplateRes;
import com.jrx.anytxn.param.dto.limit.CreditLimitTypeRes;
import com.jrx.anytxn.param.dto.limit.PrCreditLimit;
import com.jrx.anytxn.param.entity.PrCreditLimitTemplate;
import com.jrx.anytxn.param.entity.PrCreditLimitType;
import com.jrx.anytxn.param.mapper.ext.ExtPrCreditLimitTemplateMapper;
import com.jrx.anytxn.param.mapper.ext.ExtPrCreditLimitTypeMapper;
import com.jrx.anytxn.param.service.limit.ICreditLimitTemplateService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

/**
 * @author by yf
 * @Classname CreditLimitTemplateServiceImpl
 * @Description 额度模板接口实现
 * @Date 2019/6/12 0012 下午 21:05
 */
@Service
public class CreditLimitTemplateServiceImpl implements ICreditLimitTemplateService {
    private static final Logger logger = LoggerFactory.getLogger(CreditLimitTemplateServiceImpl.class);

    @Resource
    private ExtPrCreditLimitTemplateMapper extPrCreditLimitTemplateMapper;

    @Autowired
    private ISegmentService segmentService;

    @Resource
    private ExtPrCreditLimitTypeMapper extPrCreditLimitTypeMapper;


    @Override
    public TxnPage<CreditLimitTemplateRes> findAllPageByTenId(Integer pageNum, Integer pageSize, String tenantId) throws TxnException {
        Page<PrCreditLimitTemplate> page = PageHelper.startPage(pageNum, pageSize,Constant.ORDER_BY_SORT);
        List<PrCreditLimitTemplate> prCreditLimitTemplateList = extPrCreditLimitTemplateMapper.selectAllLimitTemplateByTenId(tenantId);
        if (prCreditLimitTemplateList.isEmpty()) {
            logger.error("查询的额度模板信息列表为空");
            throw new TxnException(TxnRespCode.NO_DATA.getMsg());
        }
        List<CreditLimitTemplateRes> res = BeanMapping.copyList(prCreditLimitTemplateList, CreditLimitTemplateRes.class);
        return new TxnPage<>(pageNum, pageSize, page.getTotal(), res);
    }

    @CacheEvict(value = "CREDIT_LIMIT",key = "'creditLimitTemplate_'+#tenantId+'_'+#templateId")
    @Override
    public Boolean removeLimitTemplateByTempIdAndTenId(String templateId, String tenantId) throws TxnException {
        if (StringUtils.isBlank(templateId) || StringUtils.isBlank(tenantId)) {
            logger.error("删除额度模板时额度模板ID或租户ID为空");
            throw new TxnException(TxnRespCode.NOT_EMPTY.getMsg());
        }
        int a = extPrCreditLimitTemplateMapper.deleteByTemplateIdAndTenId(tenantId, templateId);
        return a > 0;
    }

    @Override
    public CreditLimitTemplateRes findByTemplateIdAndTenId(String templateId, String tenantId) throws TxnException {
        /*判断条件是否为空，否则抛出异常*/
        if (StringUtils.isBlank(templateId) || StringUtils.isBlank(tenantId)) {
            logger.error("查询额度模板时额度模板ID或租户ID为空");
            throw new TxnException(TxnRespCode.NOT_EMPTY.getMsg());
        }
        /*查询额度模板信息(此值等会会转换后传递到controller层)*/
        PrCreditLimitTemplate template = extPrCreditLimitTemplateMapper.selectLimitTemplateByTempIdAndTenId(templateId, tenantId);
        CreditLimitTemplateRes res = BeanMapping.copy(template, CreditLimitTemplateRes.class);

        /*根据额度模板ID和组织ID查询额度树信息（额度节点ID集合）*/
        List<PrCreditLimitTemplate> creditLimitTemplateList = extPrCreditLimitTemplateMapper.selectLimitListByTempIdAndTenId(templateId, tenantId);
        List<CreditLimitTypeRes> creditLimitTypeResList = new ArrayList<>();
        for (PrCreditLimitTemplate prTemplate : creditLimitTemplateList) {
            /*通过额度节点ID查询相应额度节点信息*/
            PrCreditLimitType prCreditLimitType = extPrCreditLimitTypeMapper.selectByTenIdAndLimitId(prTemplate.getTenantId(), prTemplate.getLimitId());
            CreditLimitTypeRes creditLimitTypeRes = BeanMapping.copy(prCreditLimitType, CreditLimitTypeRes.class);
            creditLimitTypeRes.setFatherLimitId(prTemplate.getFatherLimitId());
            creditLimitTypeRes.setPercentage(prTemplate.getPercentage());
            creditLimitTypeRes.setAuthCheck(prTemplate.getAuthCheck());
            creditLimitTypeRes.setOcFlag(prTemplate.getOcFlag());
            creditLimitTypeResList.add(creditLimitTypeRes);
        }
        res.setCreditLimitTypeResList(creditLimitTypeResList);
        return res;
    }

    @Override
    public CreditLimitTypeRes findCreditLimitTypeByLimitId(String limitId, String tenantId) {
        PrCreditLimitType prCreditLimitType = extPrCreditLimitTypeMapper.selectByTenIdAndLimitId(tenantId, limitId);
        return BeanMapping.copy(prCreditLimitType, CreditLimitTypeRes.class);
    }

    @CacheEvict(value = "CREDIT_LIMIT", key = "'creditLimitTemplate_'+#creditLimitTemplateReq" +
            ".tenantId+'_'+#creditLimitTemplateReq.templateId")
    @Override
    @Transactional(rollbackFor = Exception.class)
    public CreditLimitTemplateRes modifyLimitTemplate(CreditLimitTemplateReq creditLimitTemplateReq) throws TxnException {
        PrCreditLimitTemplate prCreditLimitTemplate = BeanMapping.copy(creditLimitTemplateReq, PrCreditLimitTemplate.class);
        /*根据额度模板ID和组织ID删除所有信息*/
        extPrCreditLimitTemplateMapper.deleteByTemplateIdAndTenId(creditLimitTemplateReq.getTenantId(), creditLimitTemplateReq.getTemplateId());
        /*增加额度模板信息*/
        //确定额度模板中的额度节点不重复
        List<CreditLimitTypeRes> list = creditLimitTemplateReq.getCreditLimitTypeResList();
        if (list.isEmpty()) {
            logger.error(ErrorMsgConstant.NO_LIMIT_TYPE);
            throw new TxnBizException(TxnRespCode.NO_DATA.getCode(), TxnRespCode.NO_DATA.getMsg(ErrorMsgConstant.NO_LIMIT_TYPE));
        }
        Set<PrCreditLimitType> set = new TreeSet<>((o1, o2) -> {
            //==0表示重复
            int compareToResult = 1;
            if (o1.getLimitId().equalsIgnoreCase(o2.getLimitId())) {
                compareToResult = 0;
            }
            return compareToResult;
        });
        set.addAll(BeanMapping.copyList(list, PrCreditLimitType.class));
        if (new ArrayList<>(set).size() != list.size()) {
            logger.error("额度节点ID已存在");
            throw new TxnException("额度节点ID不能重复！");
        }
        /*增加额度模板信息*/
        prCreditLimitTemplate.setRecordVersionNumber(Constant.VERSION_NUMBER);
        for (CreditLimitTypeRes res : list) {
            String substring = res.getLimitId().substring(0, 6);
            prCreditLimitTemplate.setLimitId(substring);
            try {
                prCreditLimitTemplate.setId(segmentService.getId("PrCreditLimitTemplate"));
            } catch (SegmentException e) {
                logger.error("修改额度模板时，额度模板的主键生成错误",e);
                throw new TxnException(ErrorMsgConstant.ERROR_ID);
            }
            prCreditLimitTemplate.setAuthCheck(res.getAuthCheck());
            prCreditLimitTemplate.setPercentage(res.getPercentage());
            prCreditLimitTemplate.setOcFlag(res.getOcFlag());
            prCreditLimitTemplate.setFatherLimitId(res.getFatherLimitId());
            prCreditLimitTemplate.setUpdateBy(creditLimitTemplateReq.getUpdateBy());
            prCreditLimitTemplate.setCreateTime(creditLimitTemplateReq.getCreateTime());
            extPrCreditLimitTemplateMapper.insertSelective(prCreditLimitTemplate);
        }
        return BeanMapping.copy(prCreditLimitTemplate, CreditLimitTemplateRes.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CreditLimitTemplateRes addLimitTemplate(CreditLimitTemplateReq creditLimitTemplateReq) throws TxnException {
        PrCreditLimitTemplate prCreditLimitTemplate = BeanMapping.copy(creditLimitTemplateReq, PrCreditLimitTemplate.class);
        //确定额度模板唯一
        PrCreditLimitTemplate creditLimitTemplate = extPrCreditLimitTemplateMapper.selectLimitTemplateByTempIdAndTenId(creditLimitTemplateReq.getTemplateId(), creditLimitTemplateReq.getTenantId());
        if (creditLimitTemplate != null) {
            logger.error("增加的额度模板信息已存在");
            throw new TxnException(TxnRespCode.DATA_EXISTS, TxnRespCode.DATA_EXISTS.getMsg());
        }
        //确定额度模板中的额度节点不重复
        List<CreditLimitTypeRes> list = creditLimitTemplateReq.getCreditLimitTypeResList();
        if (list.isEmpty()) {
            logger.error(ErrorMsgConstant.NO_LIMIT_TYPE);
            throw new TxnBizException(TxnRespCode.NO_DATA.getCode(), TxnRespCode.NO_DATA.getMsg(ErrorMsgConstant.NO_LIMIT_TYPE));
        }
        Set<PrCreditLimitType> set = new TreeSet<>((o1, o2) -> {
            //==0表示重复
            int compareToResult = 1;
            if (o1.getLimitId().equalsIgnoreCase(o2.getLimitId())) {
                compareToResult = 0;
            }
            return compareToResult;
        });
        set.addAll(BeanMapping.copyList(list, PrCreditLimitType.class));
        if (new ArrayList<>(set).size() != list.size()) {
            logger.error("额度节点ID已存在");
            throw new TxnException("额度节点ID不能重复！");
        }
        /*增加额度模板信息*/
        prCreditLimitTemplate.setRecordVersionNumber(Constant.VERSION_NUMBER);
        for (CreditLimitTypeRes res : list) {
            String substring = res.getLimitId().substring(0, 6);
            try {
                prCreditLimitTemplate.setId(segmentService.getId(Constant.PR_CREDIT_LIMIT_TEMPLATE));
            } catch (SegmentException e) {
                logger.error("增加额度模板时主键生成错误",e);
                throw new TxnException(ErrorMsgConstant.ERROR_ID);
            }
            prCreditLimitTemplate.setLimitId(substring);
            prCreditLimitTemplate.setAuthCheck(res.getAuthCheck());
            prCreditLimitTemplate.setPercentage(res.getPercentage());
            prCreditLimitTemplate.setOcFlag(res.getOcFlag());
            prCreditLimitTemplate.setFatherLimitId(res.getFatherLimitId());
            extPrCreditLimitTemplateMapper.insertSelective(prCreditLimitTemplate);
        }
        return BeanMapping.copy(prCreditLimitTemplate, CreditLimitTemplateRes.class);
    }

    @Override
    public List<CreditLimitTemplateRes> findAllLimitTemplateByTenId(String tenantId) {
        List<PrCreditLimitTemplate> prCreditLimitTemplates = extPrCreditLimitTemplateMapper.selectAllLimitTemplateByTenId(tenantId);
        return BeanMapping.copyList(prCreditLimitTemplates, CreditLimitTemplateRes.class);
    }

    @Override
    @Cacheable(value = "CREDIT_LIMIT",key = "'creditLimitTemplate_'+#tenantId+'_'+#templateId")
    public List<PrCreditLimit> getPrCreditLimitListByTemIdAndOrgId(String organizationId, String templateId, String tenantId) {
        //根据 机构 模版id，租户id 查询额度模版信息
        List<PrCreditLimitTemplate> prCreditLimitTemplates = extPrCreditLimitTemplateMapper.selectPrCreditLimitList(organizationId, templateId, tenantId);
        //声明 返回集合
        List<PrCreditLimit> PrCreditLimitlist =new ArrayList<>();
        //声明 额度节点id集合
        List<String> limitList=new ArrayList<>();
        //循环额度模版 获取额度节点id 并放与集合中
        for (PrCreditLimitTemplate prCreditLimitTemplate :prCreditLimitTemplates ) {
            limitList.add(prCreditLimitTemplate.getLimitId());
        }
        //根据租户id,机构号，额度节点id集合 获取额度节点信息
        List<PrCreditLimitType> prCreditLimitTypes = extPrCreditLimitTypeMapper.selectByTenIdAndOrgIdAndLimitIds(tenantId, organizationId,limitList);
         //将额度节点转成map<limmitId,PrCreditLimitType>
        Map<String, PrCreditLimitType> map = Maps.newHashMap();
        for (PrCreditLimitType prCreditLimitType : prCreditLimitTypes) {
            map.put(prCreditLimitType.getLimitId(), prCreditLimitType);
        }
        //循环额度模版集合
        for (PrCreditLimitTemplate prCreditLimitTemplate :prCreditLimitTemplates ) {
            //将额度模版值copy到返回对象中
            PrCreditLimit copy = BeanMapping.copy(prCreditLimitTemplate, PrCreditLimit.class);
            //根据节点id获取map中额度节点
            PrCreditLimitType prCreditLimitType = map.get(prCreditLimitTemplate.getLimitId());
            //判断客户节点是否存在
            if(prCreditLimitType!=null){
                //将额度种类 放入返回对象中
                copy.setLimitClass(prCreditLimitType.getLimitClass());
                //将描述 放入返回对象中
                copy.setLimitDesc(prCreditLimitType.getLimitDesc());
                //将使用方式  是否循环放放入返回对象中
                copy.setUseMode(prCreditLimitType.getUseMode());
                //是否需要激活
                copy.setNeedActive(prCreditLimitType.getNeedActive());
            }
            //将对象放入集合中
            PrCreditLimitlist.add(copy);
        }
        //返回集合
        return PrCreditLimitlist;
    }
}
